using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;

namespace Sage.JsonConverters
{
    public static partial class SafeJsonConverters
    {
        /// <summary>
        /// 通用的安全对象转换器
        /// 专门处理第三方API返回的不一致格式：
        /// - 空数组 [] 转换为 null
        /// - 对象 {} 正常反序列化
        /// - 字符串、null等其他类型安全处理
        /// 支持 AOT 场景，可以传入源生成的 JsonTypeInfo
        /// 绝对不会抛出异常，确保程序稳定性
        /// </summary>
        /// <typeparam name="T">要转换的对象类型，必须是引用类型</typeparam>
        public sealed class SafeObjectConverter<T> : JsonConverter<T?> where T : class
        {
            private readonly JsonTypeInfo<T>? _typeInfo;
            private readonly bool _treatEmptyArrayAsNull;

            /// <summary>
            /// 默认构造函数，使用反射模式
            /// </summary>
            /// <param name="treatEmptyArrayAsNull">是否将空数组视为null，默认为true</param>
            [RequiresUnreferencedCode("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.")]
            [RequiresDynamicCode("JSON serialization and deserialization might require types that cannot be statically analyzed and might need runtime code generation. Use System.Text.Json source generation for native AOT applications.")]
            public SafeObjectConverter(bool treatEmptyArrayAsNull = true)
            {
                _typeInfo = null;
                _treatEmptyArrayAsNull = treatEmptyArrayAsNull;
            }

            /// <summary>
            /// AOT 兼容构造函数，使用源生成的 JsonTypeInfo
            /// </summary>
            /// <param name="typeInfo">源生成的类型信息</param>
            /// <param name="treatEmptyArrayAsNull">是否将空数组视为null，默认为true</param>
            public SafeObjectConverter(JsonTypeInfo<T> typeInfo, bool treatEmptyArrayAsNull = true)
            {
                _typeInfo = typeInfo ?? throw new ArgumentNullException(nameof(typeInfo));
                _treatEmptyArrayAsNull = treatEmptyArrayAsNull;
            }

            /// <summary>
            /// 从JSON读取器中安全地读取对象值
            /// </summary>
            /// <param name="reader">JSON读取器</param>
            /// <param name="typeToConvert">要转换的类型</param>
            /// <param name="options">序列化选项</param>
            /// <returns>安全转换后的对象值，失败时返回null</returns>
            [UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "The ctor is marked with RequiresUnreferencedCode.")]
            [UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "The ctor is marked with RequiresDynamicCode.")]
            public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
            {
                try
                {
                    return reader.TokenType switch
                    {
                        JsonTokenType.Null => null,
                        JsonTokenType.String => HandleStringValue(reader.GetString(), options),
                        JsonTokenType.StartArray => HandleArrayValue(ref reader),
                        JsonTokenType.StartObject => HandleObjectValue(ref reader, options),
                        JsonTokenType.True or JsonTokenType.False => HandleBooleanValue(),
                        JsonTokenType.Number => HandleNumberValue(ref reader),
                        _ => null
                    };
                }
                catch
                {
                    // 确保reader处于有效状态
                    SkipCurrentToken(ref reader);
                    return null;
                }
            }

            /// <summary>
            /// 将对象值写入JSON写入器
            /// </summary>
            /// <param name="writer">JSON写入器</param>
            /// <param name="value">要写入的对象值</param>
            /// <param name="options">序列化选项</param>
            [UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "The ctor is marked with RequiresUnreferencedCode.")]
            [UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "The ctor is marked with RequiresDynamicCode.")]
            public override void Write(Utf8JsonWriter writer, T? value, JsonSerializerOptions options)
            {
                try
                {
                    if (value == null)
                    {
                        writer.WriteNullValue();
                        return;
                    }

                    if (_typeInfo != null)
                    {
                        // AOT 模式：使用源生成的类型信息
                        JsonSerializer.Serialize(writer, value, _typeInfo);
                    }
                    else
                    {
                        // 反射模式：使用传统方式
                        JsonSerializer.Serialize(writer, value, options);
                    }
                }
                catch
                {
                    // 如果序列化失败，写入null值
                    writer.WriteNullValue();
                }
            }

            /// <summary>
            /// 处理字符串值（可能包含JSON字符串或特殊值）
            /// </summary>
            /// <param name="stringValue">字符串值</param>
            /// <param name="options">序列化选项</param>
            /// <returns>处理结果</returns>
            [RequiresUnreferencedCode("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.")]
            [RequiresDynamicCode("JSON serialization and deserialization might require types that cannot be statically analyzed and might need runtime code generation. Use System.Text.Json source generation for native AOT applications.")]
            private T? HandleStringValue(string? stringValue, JsonSerializerOptions options)
            {
                if (IsNullOrEmptyValue(stringValue))
                    return null;

                try
                {
                    // 尝试解析为JSON
                    if (_typeInfo != null)
                    {
                        return JsonSerializer.Deserialize(stringValue!, _typeInfo);
                    }
                    else
                    {
                        return JsonSerializer.Deserialize<T>(stringValue!, options);
                    }
                }
                catch
                {
                    return null;
                }
            }

            /// <summary>
            /// 处理数组值 - 关键方法，处理空数组问题
            /// </summary>
            /// <param name="reader">JSON读取器</param>
            /// <returns>处理结果</returns>
            private T? HandleArrayValue(ref Utf8JsonReader reader)
            {
                try
                {
                    // 检查是否为空数组
                    if (IsEmptyArray(ref reader))
                    {
                        return _treatEmptyArrayAsNull ? null : default;
                    }

                    // 非空数组的情况
                    // 但是如果有其他需求，可以在这里添加特殊处理逻辑
                    SkipCurrentToken(ref reader);
                    return null;
                }
                catch
                {
                    SkipCurrentToken(ref reader);
                    return null;
                }
            }

            /// <summary>
            /// 处理对象值 - 正常的反序列化路径
            /// </summary>
            /// <param name="reader">JSON读取器</param>
            /// <param name="options">序列化选项</param>
            /// <returns>处理结果</returns>
            [RequiresUnreferencedCode("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.")]
            [RequiresDynamicCode("JSON serialization and deserialization might require types that cannot be statically analyzed and might need runtime code generation. Use System.Text.Json source generation for native AOT applications.")]
            private T? HandleObjectValue(ref Utf8JsonReader reader, JsonSerializerOptions options)
            {
                try
                {
                    if (_typeInfo != null)
                    {
                        // AOT 模式：使用源生成的类型信息
                        return JsonSerializer.Deserialize(ref reader, _typeInfo);
                    }
                    else
                    {
                        // 反射模式：使用传统方式
                        return JsonSerializer.Deserialize<T>(ref reader, options);
                    }
                }
                catch
                {
                    // 如果反序列化失败，跳过当前对象
                    SkipCurrentToken(ref reader);
                    return null;
                }
            }

            /// <summary>
            /// 处理布尔值（某些API可能返回布尔值表示有无数据）
            /// </summary>
            /// <returns>处理结果，通常返回null</returns>
            private static T? HandleBooleanValue()
            {
                // 布尔值通常不能转换为复杂对象
                // 如果有特殊需求，可以在这里添加逻辑
                return null;
            }

            /// <summary>
            /// 处理数字值（某些API可能返回数字表示状态）
            /// </summary>
            /// <param name="reader">JSON读取器</param>
            /// <returns>处理结果，通常返回null</returns>
            private static T? HandleNumberValue(ref Utf8JsonReader reader)
            {
                try
                {
                    // 消费数字token，但不使用其值
                    reader.GetDecimal();
                    return null;
                }
                catch
                {
                    return null;
                }
            }

            /// <summary>
            /// 检查是否为null或空值字符串
            /// </summary>
            /// <param name="value">要检查的字符串</param>
            /// <returns>是否为空值</returns>
            private static bool IsNullOrEmptyValue(string? value)
            {
                return string.IsNullOrWhiteSpace(value) ||
                       value.Equals("null", StringComparison.OrdinalIgnoreCase) ||
                       value.Equals("undefined", StringComparison.OrdinalIgnoreCase) ||
                       value.Equals("\"\"", StringComparison.OrdinalIgnoreCase) ||
                       value.Equals("{}", StringComparison.OrdinalIgnoreCase) ||
                       value.Equals("[]", StringComparison.OrdinalIgnoreCase);
            }

            /// <summary>
            /// 检查是否为空数组 - 核心方法
            /// 这个方法解决了你的核心问题：区分 [] 和有内容的数组
            /// </summary>
            /// <param name="reader">JSON读取器</param>
            /// <returns>是否为空数组</returns>
            private static bool IsEmptyArray(ref Utf8JsonReader reader)
            {
                // 创建reader副本来检查，避免影响原reader
                var readerCopy = reader;

                // 确认当前位置是StartArray
                if (readerCopy.TokenType != JsonTokenType.StartArray)
                    return false;

                // 读取下一个token
                if (!readerCopy.Read())
                    return false;

                // 如果直接是EndArray，说明是空数组 []
                if (readerCopy.TokenType == JsonTokenType.EndArray)
                {
                    // 正确跳过整个空数组
                    // 跳过 StartArray
                    reader.Read();
                    // 跳过 EndArray
                    reader.Read();
                    return true;
                }

                // 不是空数组
                return false;
            }

            /// <summary>
            /// 安全地跳过当前token及其内容
            /// 确保reader处于正确的状态，避免后续解析出错
            /// </summary>
            /// <param name="reader">JSON读取器</param>
            private static void SkipCurrentToken(ref Utf8JsonReader reader)
            {
                try
                {
                    // 对于复合类型（对象或数组），需要跳过整个结构
                    if (reader.TokenType == JsonTokenType.StartObject ||
                        reader.TokenType == JsonTokenType.StartArray)
                    {
                        // 使用JsonDocument.ParseValue来跳过整个结构
                        JsonDocument.ParseValue(ref reader);
                    }
                    // 对于简单类型，reader已经在正确位置，无需额外操作
                }
                catch
                {
                    // 如果跳过失败，忽略异常
                    // 这种情况很少见，通常是JSON格式严重错误
                }
            }
        }

        /// <summary>
        /// 为源生成和AOT场景提供的便利工厂类
        /// 简化转换器的创建和配置过程
        /// </summary>
        public static class ObjectConverterFactory
        {
            /// <summary>
            /// 创建AOT兼容的对象转换器
            /// 推荐在源生成场景下使用
            /// </summary>
            /// <typeparam name="T">目标类型</typeparam>
            /// <param name="typeInfo">源生成的类型信息</param>
            /// <param name="treatEmptyArrayAsNull">是否将空数组视为null，默认true</param>
            /// <returns>配置好的转换器实例</returns>
            public static SafeObjectConverter<T> Create<T>(JsonTypeInfo<T> typeInfo, bool treatEmptyArrayAsNull = true)
                where T : class
            {
                return new SafeObjectConverter<T>(typeInfo, treatEmptyArrayAsNull);
            }

            /// <summary>
            /// 创建反射模式的对象转换器
            /// 适用于非AOT场景
            /// </summary>
            /// <typeparam name="T">目标类型</typeparam>
            /// <param name="treatEmptyArrayAsNull">是否将空数组视为null，默认true</param>
            /// <returns>配置好的转换器实例</returns>
            [RequiresUnreferencedCode("JSON serialization and deserialization might require types that cannot be statically analyzed.")]
            [RequiresDynamicCode("JSON serialization and deserialization might require types that cannot be statically analyzed.")]
            public static SafeObjectConverter<T> Create<T>(bool treatEmptyArrayAsNull = true)
                where T : class
            {
                return new SafeObjectConverter<T>(treatEmptyArrayAsNull);
            }

            /// <summary>
            /// 批量创建多个对象转换器（AOT版本）
            /// 适合需要为多个类型创建转换器的场景
            /// </summary>
            /// <param name="typeInfos">类型信息字典</param>
            /// <param name="treatEmptyArrayAsNull">是否将空数组视为null</param>
            /// <returns>转换器列表</returns>
            public static List<JsonConverter> CreateMultiple(
                Dictionary<Type, JsonTypeInfo> typeInfos,
                bool treatEmptyArrayAsNull = true)
            {
                var converters = new List<JsonConverter>();

                foreach (var kvp in typeInfos)
                {
                    var converterType = typeof(SafeObjectConverter<>).MakeGenericType(kvp.Key);
                    var converter = Activator.CreateInstance(converterType, kvp.Value, treatEmptyArrayAsNull);
                    if (converter != null)
                    {
                        converters.Add((JsonConverter)converter);
                    }
                }

                return converters;
            }
        }
    }
}